package cn.sixmillions.ps.controller;


import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.sixmillions.ps.common.base.R;
import cn.sixmillions.ps.config.MinioConfig;
import cn.sixmillions.ps.config.QingStorConfig;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.qingstor.sdk.exception.QSException;
import com.qingstor.sdk.service.Bucket;
import com.qingstor.sdk.service.Types;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.errors.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * markdown预览(TtMdPreview)表控制层
 *
 * @author six
 * @since 2023-01-12
 */
@RestController
@RequestMapping("/api/qing-stor")
@RequiredArgsConstructor
@Slf4j
@CrossOrigin("*")
public class QingStorController {

    final private Bucket qingStorBucket;
    final private QingStorConfig qingStorConfig;
    final private MinioConfig minioConfig;
    final private MinioClient minioClient;

    @PostMapping("/single-upload")
    public R upload(MultipartFile file) throws IOException, QSException {
        //获取文件名
        String originalFilename = file.getOriginalFilename();
        //获取文件后缀名
        String suffixName = originalFilename.substring(originalFilename.lastIndexOf(StringPool.DOT));
        String folder = DateUtil.format(new Date(), DatePattern.SIMPLE_MONTH_PATTERN);
        String newFileName = String.format("%s%s%s",
                DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN),
                RandomUtil.randomString(4),
                suffixName);
        Bucket.PutObjectInput input = new Bucket.PutObjectInput();
        input.setBodyInputStream(file.getInputStream());
        String fullPath = String.format("%s/%s", folder, newFileName);
        qingStorBucket.putObject(fullPath, input);
        return R.data(String.format("%s/%s", qingStorConfig.getBaseUrl(), fullPath));
    }

    /**
     * 删除文件
     * 多个文件名逗号分隔
     * 全路径文件名：202301/xxx.png
     *
     * @param fileNames 文件名
     * @return
     * @throws QSException
     */
    @GetMapping("/remove")
    public R delete(String fileNames) throws QSException {
        if (StringUtils.isBlank(fileNames)) {
            return R.fail("缺少fileNames参数");
        }
        String[] fileNameArr = fileNames.split(StringPool.COMMA);
        for (String fileName : fileNameArr) {
            Bucket.DeleteObjectOutput res = qingStorBucket.deleteObject(fileName);
            log.info("删除文件{}，删除结果：{}", fileName, JSON.toJSONString(res));
        }
        return R.success();
    }

    /**
     * 获取所有对象
     */
    @GetMapping("/list-all")
    public R listAllObj() throws QSException, IOException {
        Bucket.ListObjectsOutput listObjectsOutput = qingStorBucket.listObjects(null);
        List<Types.KeyModel> objectKeys = listObjectsOutput.getKeys();
        if (objectKeys != null && !objectKeys.isEmpty()) {
            return R.data(objectKeys.stream().map(Types.KeyModel::getKey).collect(Collectors.toList()));
        }
        return R.success();
    }

    /**
     * 将青云oss的数据迁移到minio
     * 青云格式：202301/202301301855391237pvw.png
     * minio格式：2023/01/30/1855391237pvw.png
     */
    @GetMapping("/move-to-minio")
    public void moveToMinio() throws QSException, ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        Bucket.ListObjectsOutput listObjectsOutput = qingStorBucket.listObjects(null);
        List<Types.KeyModel> objectKeys = listObjectsOutput.getKeys();
        for (Types.KeyModel objectKey : objectKeys) {
            if (objectKey.getKey().contains("log")) {
                continue;
            }
            moveObj(objectKey);
        }
    }

    private void moveObj(Types.KeyModel objectKey) throws QSException, ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        Bucket.GetObjectInput input = new Bucket.GetObjectInput();
        String name = objectKey.getKey();
        String fullPath = String.format("%s/%s/%s/%s", name.substring(7, 11), name.substring(11, 13), name.substring(13, 15), name.substring(15));
        //下载qing-stor数据
        Bucket.GetObjectOutput output = qingStorBucket.getObject(name, input);
        InputStream inputStream = output.getBodyInputStream();
        //上传minio
        PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(minioConfig.getBucketName())
                .object(fullPath)
                .stream(inputStream, objectKey.getSize(), -1)
                .contentType(objectKey.getMimeType())
                .build();
        minioClient.putObject(objectArgs);
    }

}

